﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace ExpressionToWhere
{
    /// <summary>
    /// worker.Id == 1+(int)(id/3)中用来计算(int)(id/3)的值
    /// </summary>
    internal class ConstantUnaryExpressionVisitor : ConstantExpressionVisitor
    {
        protected override Expression VisitUnary(UnaryExpression node)
        {
            object parameterValue = ExpressionProcesser.GetConstant(node.Operand);
            if (node.NodeType == ExpressionType.Convert)
            {
                Value = HandleConvert(node.Type, parameterValue);
            }
            return node;
        }

        private object HandleConvert(Type type, object parameterValue)
        {
            if (parameterValue == null)
            {
                return parameterValue;
            }
            //(int)(2m/3)==1但(int)(2.0/3)==0，所以decimal类型要单独处理
            if (type == typeof(int) || type == typeof(int?))
            {
                if (parameterValue is decimal) return Convert.ToInt32(parameterValue);
                return Math.Floor(Convert.ToDouble(parameterValue));
            }
            if (type == typeof(float) || type == typeof(float?))
            {
                return Convert.ToSingle(parameterValue);
            }
            if (type == typeof(double) || type == typeof(double?))
            {
                return Convert.ToDouble(parameterValue);
            }
            if (type == typeof(decimal) || type == typeof(decimal?))
            {
                return Convert.ToDecimal(parameterValue);
            }
            if (type == typeof(char))
            {
                return Convert.ToChar(parameterValue);
            }
            if (type == typeof(string))
            {
                return Convert.ToString(parameterValue);
            }
            if (type == typeof(DateTime) || type == typeof(DateTime?))
            {
                return Convert.ToDateTime(parameterValue);
            }
            throw new NotSupportedException($"Unknow Type {type}");
        }
    }
}
